package com.james.codeauto.util;

import com.james.codeauto.common.StringUtils;
import com.james.codeauto.tools.json.JSONArray;
import com.james.codeauto.tools.json.JSONObject;
import com.james.codeauto.web.HttpClient;
import org.apache.poi.ooxml.POIXMLDocument;
import org.apache.poi.ooxml.extractor.POIXMLTextExtractor;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.IBodyElement;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.commonmark.Extension;
import org.commonmark.ext.gfm.tables.TablesExtension;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

/**
 * @Author：hp
 * @Description：
 * @Date：2021年11月4日14:58:11
 * @Modified by：读取word所有内容
 **/
public class LiveDocUtil {


    private static  JSONArray getAllPages(JSONArray catalogs, JSONArray allPages) {
        for (int i = 0; i < catalogs.length(); i++) {
            JSONObject jsonObject = catalogs.getJSONObject(i);
            if(jsonObject.optJSONArray("child") ==null ||jsonObject.optJSONArray("child").length()==0){
                allPages.put(jsonObject.optJSONObject("local"));
                continue;
            }
            if (jsonObject.optJSONArray("child").length() > 0) {
                return  getAllPages(jsonObject.optJSONArray("child"), allPages);
            }else{
                allPages.put(jsonObject.optJSONObject("local"));
            }

        }
        return allPages;
    }

    public static void main(String[] args) {

        // String content = readWord(parseDocFromGreenCloudPath());
        // System.out.println(content);
        parseInfoList();
    }

    public  static List<Map<String, Object>>   parseInfoList(){
        try {
            //

            JSONObject jsonObject = new JSONObject();
            String html = HttpClient.doGetForJson("https://saas-doc-api.vhall.com/document/detail/get-left-menu?doc_id=947", jsonObject);
            JSONObject data = new JSONObject(html);
            JSONArray info = data.getJSONObject("data").getJSONArray("menu");
            info.remove(0);
            info.remove(0);
            info.remove(info.length()-1);
            JSONArray pages = new JSONArray();
            for (int i = 0; i < info.length(); i++) {
                JSONArray t = getAllPages(new JSONArray().put(info.getJSONObject(i)), new JSONArray());
                for (int j = 0; j < t.length(); j++) {
                    pages.put(t.getJSONObject(j));
                }
            }


          return   paseHtmlData(pages);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static  List<Map<String, Object>> paseHtmlData(JSONArray pages) {

        List<Map<String, Object>> listData = new ArrayList<>();
        for (int i = 0; i < pages.length(); i++) {
            JSONObject page = pages.getJSONObject(i);

            String result = HttpClient.doGetForJson("https://saas-doc-api.vhall.com/document/detail/indexJson?project_id="+page.optInt("project_id")+"&doc_id="+page.optInt("doc_id"), page);
            String data = new JSONObject(result).optJSONObject("data").optString("body");
            if (data == null) {
                continue;
            }
            try {
                Map<String, Object> intA = parseHtmlData(data);
                if(intA!=null){
                    listData.add(intA);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        //Document doc = Jsoup.parse(html);
        return listData;
    }

    public static Map<String, Object>parseHtmlData(String htmlText) throws Exception {
        HashSet<String> paramKeyTypes = new HashSet<>();

        System.out.println(htmlText);
        Document doc = Jsoup.parse(htmlText);

        Elements h2Element = doc.getElementsByTag("h3");
        System.out.println(h2Element.size());



        Elements tbodyElement = doc.getElementsByTag("tbody");

        int tbodyElementSize = tbodyElement.size() / 4;
        System.out.println(tbodyElementSize + "");//4个一组

        Map<String, Object> parseMap = new HashMap<>();
        String title = doc.getElementsByTag("h1").get(0).text().trim();

        parseMap.put("title" , title.substring(0,title.indexOf("更新时间")));
        parseMap.put("desc" , h2Element.get(1).nextElementSibling().text().trim());
        String methodDesc = h2Element.get(0).nextElementSibling().text().replace("·" , "").trim();
       String[] methods = methodDesc.split(" ");
        parseMap.put("url" , methods[1].trim() );
        parseMap.put("method" ,methods[0].trim());
        int i=0;

        Elements table1Element = tbodyElement.get(0).getElementsByTag("tr");
        JSONArray paramInfo = new JSONArray();
        for (int j = 0; j < table1Element.size(); j++) {
            Elements table1TdElement = table1Element.get(j).getElementsByTag("td");
            if(table1TdElement==null){
                continue;
            }
            JSONObject jsonObjectParam = new JSONObject();
            for (int k = 0; k < table1TdElement.size(); k++) {
                Element td = table1TdElement.get(k);
                String paramStr = td.text();
                if (k == 0) {
                    //参数名

                    jsonObjectParam.put("name" , paramStr.trim());
                    jsonObjectParam.put("realName" , paramStr.trim());
                } else if (k == 2) {
                    //必选
                    jsonObjectParam.put("require" , paramStr.trim());

                } else if (k == 1) {

                    paramKeyTypes.add(paramStr);
                    //默认值
                    jsonObjectParam.put("type" , paramStr);
                } else if (k == 3) {
                    //说明
                    jsonObjectParam.put("desc" , paramStr);
                    jsonObjectParam.put("defaultValue" , "");
                    jsonObjectParam.put("descMore" , "");
                }

                System.out.println(paramStr);
            }
            if (jsonObjectParam.get("name").toString().contains("参数")) {
                continue;
            }
            if (jsonObjectParam.get("name").toString().contains("类型")) {
                continue;
            }
            if (jsonObjectParam.get("name").toString().equals("是否必须")) {
                continue;
            }

            if (jsonObjectParam.get("name").toString().contains("含义")) {
                continue;
            }

            jsonObjectParam.put("treeNode" , "0");
            String reuqire = (String) jsonObjectParam.get("require");
            String type = (String) jsonObjectParam.get("type");
            if ("是".equals(reuqire) || "否".equals(reuqire)) {

            } else {
                jsonObjectParam.put("type" , reuqire);
                jsonObjectParam.put("require" , type);
            }
            paramInfo.put(jsonObjectParam);
        }
        parseMap.put("paramList" , paramInfo);
        Elements table2Element = tbodyElement.get( 1).getElementsByTag("tr");
        JSONArray responseParamInfo = new JSONArray();

        for (int j = 0; j < table2Element.size(); j++) {
            Elements table2TdElement = table2Element.get(j).getElementsByTag("td");
            if(table2TdElement==null){
                continue;
            }
            JSONObject jsonObjectParam = new JSONObject();
            int len = table2TdElement.size();
            for (int k = 0; k < len; k++) {
                Element td = table2TdElement.get(k);

                String responseParamStr = td.text();
                System.out.println(responseParamStr);
                if (k == 0) {
                    //参数名

                    jsonObjectParam.put("name" , responseParamStr.trim());
                    jsonObjectParam.put("realName" , responseParamStr.trim());
                } else if (k == 2) {
                    //必选
                    jsonObjectParam.put("require" , responseParamStr.trim());

                } else if (k == 1) {

                    paramKeyTypes.add(responseParamStr);
                    //默认值
                    jsonObjectParam.put("type" , responseParamStr.trim());
                } else if (k == 3) {
                    //说明
                    jsonObjectParam.put("desc" , responseParamStr);
                    jsonObjectParam.put("defaultValue" , "");
                    jsonObjectParam.put("descMore" , "");
                }
                System.out.println(responseParamStr);
            }
            if (jsonObjectParam.get("name").toString().contains("参数")) {
                continue;
            }
            if (jsonObjectParam.get("name").toString().contains("类型")) {
                continue;
            }
            if (jsonObjectParam.get("name").toString().equals("是否必须")) {
                continue;
            }

            if (jsonObjectParam.get("name").toString().contains("含义")) {
                continue;
            }
            jsonObjectParam.put("treeNode" , "0");
            String reuqire = (String) jsonObjectParam.get("require");
            String type = (String) jsonObjectParam.get("type");
            if ("是".equals(reuqire) || "否".equals(reuqire)) {

            } else {
                jsonObjectParam.put("type" , reuqire);
                jsonObjectParam.put("require" , type);
            }
            responseParamInfo.put(jsonObjectParam);

        }
        parseMap.put("responseParamList" , responseParamInfo);

        //构造json
        Elements table1JsonElement = tbodyElement.get( 0).getElementsByTag("tr");

        JSONObject jsonParamObject =ParkingLotYuShiDocUtil.convertListParamToJsonObj(true, paramInfo, parseMap);
        parseMap.put("paramJson" , jsonParamObject);
        parseMap.put("paramJsonStr" , jsonParamObject.toString(4));

        JSONObject responseJsonParamObject =ParkingLotYuShiDocUtil.convertListParamToJsonObj(true, responseParamInfo, parseMap);
        parseMap.put("responseJson" , responseJsonParamObject);
        String content =  doc.getElementsByTag("pre").last().getElementsByTag("code").last().text();
        System.out.println(content);
         try{
             JSONObject result = new JSONObject(content);
             parseMap.put("responseParamJsonStr" , result.optJSONObject("data").toString(4));
         }catch (Exception e){
             e.printStackTrace();
             parseMap.put("responseParamJsonStr" , responseJsonParamObject.toString(4));
         }



        JSONObject response = (JSONObject) parseMap.get("responseJson");
        if (response.opt("data") != null) {
            if (StringUtils.isNotBlank(response.optString("page_size"))||
                    StringUtils.isNotBlank(response.optString("limit"))) {
                parseMap.put("hasPage" , "true");
            }
            if (response.get("data") instanceof JSONArray) {
                parseMap.put("responseJson" , response.optJSONArray("data"));
            } else {
                parseMap.put("responseJson" , response.optJSONObject("data"));
            }
        }

        JSONObject paramJson = (JSONObject) parseMap.get("paramJson");
        if (paramJson.opt("data") != null) {
            if (paramJson.get("data") instanceof JSONArray) {
                parseMap.put("paramJson" , paramJson.optJSONArray("data"));
            } else {
                parseMap.put("paramJson" , paramJson.optJSONObject("data"));
            }
        }



        String reqJsonCommentStr = "";
        for (int j = 0; j < paramInfo.length(); j++) {
            JSONObject reqParamObject = paramInfo.getJSONObject(j);
            String desc = reqParamObject.optString("desc");
            if (!StringUtils.isNotBlank(desc)) {
                desc = reqParamObject.getString("name");
            }
            reqJsonCommentStr += reqParamObject.getString("name") + "\t";
            reqJsonCommentStr += desc + "\t";
            reqJsonCommentStr += reqParamObject.optString("type") + "\t";
            reqJsonCommentStr += reqParamObject.optString("require") + "\t";
            reqJsonCommentStr += "" + "\t";
            reqJsonCommentStr += desc + "\n";

        }
        parseMap.put("reqJsonCommentStr" , reqJsonCommentStr);

        String jsonCommentStr = "";
        for (int j = 0; j < responseParamInfo.length(); j++) {
            JSONObject responseParamObject = responseParamInfo.getJSONObject(j);
            String desc = responseParamObject.optString("desc");
            if (!StringUtils.isNotBlank(desc)) {
                desc = responseParamObject.getString("name");
            }
            jsonCommentStr += responseParamObject.getString("name") + "\t";
            jsonCommentStr += desc + "\t";
            jsonCommentStr += responseParamObject.optString("type") + "\t";
            jsonCommentStr += responseParamObject.optString("require") + "\t";
            jsonCommentStr += "" + "\t";
            jsonCommentStr += desc + "\n";

        }
        parseMap.put("jsonCommentStr" , jsonCommentStr);

        checkSaveMarkdownToFile(parseMap);

        System.out.println("paramKeyTypes===" + paramKeyTypes.toString());
        return parseMap;
    }

    private static int currentIndex = 0;

    //number, boolean, string, integer, object, object [], string [],
    public static JSONObject convertListParamToJsonObj(Elements jsonEle) {

        String info = jsonEle.text().trim();
        JSONObject jsonObject = new JSONObject(info);
        return jsonObject;
    }

    private static JSONObject parseParam(JSONArray paramInfo, JSONObject paramObj, JSONObject jsonObject, int currentNode) {
        String name = paramObj.optString("name").trim();
        if (StringUtils.isNotBlank(name)) {
            String type = paramObj.optString("type");
            if (type.equals("number")) {
                jsonObject.put(name, 1.0);
            } else if (type.equals("integer")) {
                jsonObject.put(name, 1);
            } else if (type.equals("boolean")) {
                jsonObject.put(name, true);
            } else if (type.equals("string []")) {
                JSONArray childObjArray = new JSONArray();
                childObjArray.put("String");
                jsonObject.put(name, childObjArray);
            } else if (type.equals("object")) {
                JSONObject childObj = new JSONObject();
                //treeNodeCheck
                currentIndex++;
                childObj = parseParam(paramInfo, paramInfo.getJSONObject(currentIndex), childObj, Integer.parseInt(paramObj.getString("treeNode")) + 1);
                jsonObject.put(name, childObj);
            } else if (type.equals("object []")) {
                JSONArray childObjArray = new JSONArray();
                //treeNodeCheck
                currentIndex++;
                for (int i = 0; i < 1; i++) {
                    JSONObject childObj = new JSONObject();
                    childObj = parseParam(paramInfo, paramInfo.getJSONObject(currentIndex), childObj, Integer.parseInt(paramObj.getString("treeNode")) + 1);
                    childObjArray.put(childObj);
                }
                jsonObject.put(name, childObjArray);
            } else if (type.equals("string")) {
                String defaultValue = paramObj.optString("defaultValue");
                if (StringUtils.isNotBlank(defaultValue)) {
                    jsonObject.put(name, defaultValue);
                } else {
                    jsonObject.put(name, "String");
                }

            }

            if (currentNode == Integer.parseInt(paramObj.getString("treeNode"))) {
                //in sub node
                if (paramInfo.length() > currentIndex + 1) {
                    JSONObject paramCheck = paramInfo.getJSONObject(currentIndex + 1);
                    if (currentNode == Integer.parseInt(paramCheck.getString("treeNode"))) {
                        //still the same
                        currentIndex++;
                        jsonObject = parseParam(paramInfo, paramCheck, jsonObject, Integer.parseInt(paramObj.getString("treeNode")));
                    }


                }

            }
        }
        return jsonObject;
    }

    static boolean saveMarkDownFile = false;

    private static void checkSaveMarkdownToFile(Map<String, Object> parseMap) throws Exception {
        if (saveMarkDownFile) {
            String title = (String) parseMap.get("title");
            String fileName = title.replaceAll("/" , "-") + ".md";
            // 从JDK1.7开始提供的方法
            // 使用Files.write创建一个文件并写入
            try {
                Files.write(Paths.get(fileName), GenMarkDownUtils.generatorCode(parseMap).getBytes(StandardCharsets.UTF_8));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static String parseHtmlFromGreenCloudPath() {
        String html = "ACS5.0开放平台接入文档 V1.0.4.html";
        String path = Paths.get("doc" , html).toAbsolutePath().toString();
        return path;
    }

    public static String parseDocFromGreenCloudPath() {
        String html = "绿云会员接口手册.docx";
        String path = Paths.get("doc" , html).toAbsolutePath().toString();
        return path;
    }

    public static String processParagraphs(XWPFParagraph paragraph, XWPFDocument doc) {

        List<XWPFRun> runs = paragraph.getRuns();
        String paragraphText = "";
        for (XWPFRun run : runs) {
            String text = run.getText(0);                                                                       //分段是poi来完成的,但是它分段的时候可能出现${CJ_CP}${CL_LX}这种情况
            System.out.println("text---->" + text);
            if (text != null) {
                paragraphText += text;
            }
        }
        System.out.println("@@@@=" + paragraphText);
        return paragraphText;
    }

    public static String readWord(String path) {
        String buffer = "";
        try {
            if (path.endsWith(".docx")) {
                InputStream is2 = new FileInputStream(new File(path));
                XWPFDocument docx = new XWPFDocument(is2);
                for (int i = 0; i < docx.getBodyElements().size(); i++) {
                    IBodyElement element = docx.getBodyElements().get(i);
                    if (element instanceof XWPFParagraph) {
                        XWPFParagraph xwpfParagraph = (XWPFParagraph) element;
                        processParagraphs(xwpfParagraph, docx);
                    } else {
                        //table.

                    }
                }
                int tables = docx.getTables().size();
                System.out.println(tables);
                docx.close();

                OPCPackage opcPackage = POIXMLDocument.openPackage(path);
                POIXMLTextExtractor extractor = new XWPFWordExtractor(opcPackage);
                buffer = extractor.getText();
                extractor.close();
            }
//            else if (path.endsWith("docx")) {
//                OPCPackage opcPackage = POIXMLDocument.openPackage(path);
//                POIXMLTextExtractor extractor = new XWPFWordExtractor(opcPackage);
//                buffer = extractor.getText();
//                extractor.close();
//            }
            else {
                System.out.println("此文件不是word文件！");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return buffer;
    }
}
